package com.example.computer_exam_training_sys.service.impl;

import com.example.computer_exam_training_sys.dto.LearningProgressDTO;
import com.example.computer_exam_training_sys.entity.UserLearningProgress;
import com.example.computer_exam_training_sys.mapper.UserLearningProgressMapper;
import com.example.computer_exam_training_sys.service.UserLearningProgressService;
import com.example.computer_exam_training_sys.service.UserStudyPlanService;
import com.example.computer_exam_training_sys.vo.LearningProgressVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
public class UserLearningProgressServiceImpl implements UserLearningProgressService {

    @Autowired
    private UserLearningProgressMapper mapper;
    
    @Autowired
    private UserStudyPlanService studyPlanService;

    /**
     * 自动更新用户所有课程的学习进度
     * 通过user_id关联user_practices和user_exams计算完成率
     * 通过user_id关联user_study_plans更新学习计划进度
     */
    @Override
    @Transactional
    public void autoUpdateAllProgress(Long userId) {
        try {
            // 获取用户所有课程
            List<Long> courseIds = mapper.getCourseIdsByUserId(userId);
            
            // 如果没有课程记录，尝试从练习和考试记录中获取
            if (courseIds == null || courseIds.isEmpty()) {
                List<Long> practicesCourseIds = mapper.getCourseIdsFromPractices(userId);
                List<Long> examsCourseIds = mapper.getCourseIdsFromExams(userId);
                
                // 合并两个列表并去重
                courseIds = new ArrayList<>();
                if (practicesCourseIds != null) {
                    courseIds.addAll(practicesCourseIds);
                }
                if (examsCourseIds != null) {
                    courseIds.addAll(examsCourseIds);
                }
                courseIds = courseIds.stream().distinct().collect(Collectors.toList());
            }
            
            if (courseIds != null && !courseIds.isEmpty()) {
                for (Long courseId : courseIds) {
                    // 计算课程完成率
                    Double completionRate = calculateCourseCompletionRate(userId, courseId);
                    
                    // 更新课程学习进度
                    updateCourseLearningProgress(userId, courseId, completionRate, 0);
                    
                    // 更新学习计划进度
                    updateStudyPlanProgress(userId, courseId);
                }
            }
        } catch (Exception e) {
            throw new RuntimeException("自动更新学习进度失败: " + e.getMessage(), e);
        }
    }

    @Override
    public List<LearningProgressDTO> getCourseProgress(Long userId) {
        List<Map<String, Object>> progressWithCourseInfo = mapper.findProgressWithCourseInfo(userId);
        List<LearningProgressDTO> result = new ArrayList<>();
        
        for (Map<String, Object> map : progressWithCourseInfo) {
            LearningProgressDTO dto = new LearningProgressDTO();
            dto.setProgressId((Long) map.get("progress_id"));
            dto.setUserId((Long) map.get("user_id"));
            dto.setCourseId((Long) map.get("course_id"));
            dto.setCourseName((String) map.get("course_name"));
            dto.setCompletionRate((Double) map.get("completion_rate"));
            dto.setTotalStudyTime((Integer) map.get("total_study_time"));
            dto.setStatus((String) map.get("status"));
            
            // 获取练习和考试相关数据
            Long courseId = (Long) map.get("course_id");
            dto.setPracticeCount(mapper.countPracticesByUserAndCourse(userId, courseId));
            dto.setExamCount(mapper.countExamsByUserAndCourse(userId, courseId));
            dto.setAverageScore(mapper.getAverageScoreByUserAndCourse(userId, courseId));
            
            result.add(dto);
        }
        
        return result;
    }

    @Override
    public LearningProgressVO getProgressOverview(Long userId) {
        List<UserLearningProgress> progressList = mapper.findByUserId(userId);
        LearningProgressVO overview = new LearningProgressVO();
        overview.setUserId(userId);
        
        if (!progressList.isEmpty()) {
            double avgCompletionRate = progressList.stream()
                    .mapToDouble(UserLearningProgress::getCompletionRate)
                    .average()
                    .orElse(0.0);
            
            int totalStudyTime = progressList.stream()
                    .mapToInt(UserLearningProgress::getTotalStudyTime)
                    .sum();
            
            long completedCount = progressList.stream()
                    .filter(p -> "completed".equals(p.getStatus()))
                    .count();
            
            overview.setAverageCompletionRate(avgCompletionRate);
            overview.setTotalStudyTime(totalStudyTime);
            overview.setCompletedCount(Long.valueOf(completedCount));
            overview.setTotalCount(Long.valueOf(progressList.size()));
        }
        
        return overview;
    }

    @Override
    public LearningProgressVO getWeakPointsAnalysis(Long userId) {
        List<UserLearningProgress> progressList = mapper.findByUserId(userId);
        LearningProgressVO analysis = new LearningProgressVO();
        analysis.setUserId(userId);
        
        if (!progressList.isEmpty()) {
            // 找出完成率最低的三个项目
            List<UserLearningProgress> weakPoints = progressList.stream()
                    .filter(p -> p.getCompletionRate() < 100)
                    .sorted((p1, p2) -> Double.compare(p1.getCompletionRate(), p2.getCompletionRate()))
                    .limit(3)
                    .collect(Collectors.toList());
            
            analysis.setWeakPoints(weakPoints.stream()
                    .map(p -> String.format("课程ID: %d, 完成率: %.2f%%", p.getCourseId(), p.getCompletionRate()))
                    .collect(Collectors.toList()));
            
            // 生成学习建议
            if (!weakPoints.isEmpty()) {
                StringBuilder advice = new StringBuilder("建议重点关注以下内容：\n");
                for (UserLearningProgress point : weakPoints) {
                    advice.append(String.format("- 课程ID %d 的复习，当前完成率 %.2f%%\n", 
                            point.getCourseId(), point.getCompletionRate()));
                }
                analysis.setStudyAdvice(advice.toString());
            }
        }
        
        return analysis;
    }
    
    @Override
    public LearningProgressDTO getCourseLearningProgress(Long userId, Long courseId) {
        UserLearningProgress progress = mapper.findByUserIdAndCourseId(userId, courseId);
        if (progress == null) {
            // 如果没有记录，创建一个新的进度对象
            LearningProgressDTO dto = new LearningProgressDTO();
            dto.setUserId(userId);
            dto.setCourseId(courseId);
            dto.setCompletionRate(0.0);
            dto.setTotalStudyTime(0);
            dto.setStatus("not_started");
            
            // 获取练习和考试相关数据
            dto.setPracticeCount(mapper.countPracticesByUserAndCourse(userId, courseId));
            dto.setExamCount(mapper.countExamsByUserAndCourse(userId, courseId));
            dto.setAverageScore(mapper.getAverageScoreByUserAndCourse(userId, courseId));
            
            return dto;
        }
        
        LearningProgressDTO dto = convertToDTO(progress);
        
        // 获取练习和考试相关数据
        dto.setPracticeCount(mapper.countPracticesByUserAndCourse(userId, courseId));
        dto.setExamCount(mapper.countExamsByUserAndCourse(userId, courseId));
        dto.setAverageScore(mapper.getAverageScoreByUserAndCourse(userId, courseId));
        
        return dto;
    }
    
    @Override
    @Transactional
    public void updateCourseLearningProgress(Long userId, Long courseId, Double completionRate, Integer studyTime) {
        UserLearningProgress progress = mapper.findByUserIdAndCourseId(userId, courseId);
        
        if (progress == null) {
            progress = new UserLearningProgress();
            progress.setUserId(userId);
            progress.setCourseId(courseId);
            progress.setCompletionRate(completionRate);
            progress.setTotalStudyTime(studyTime);
            progress.setStatus("in_progress");
            progress.setCreateTime(LocalDateTime.now());
            mapper.insert(progress);
        } else {
            progress.setCompletionRate(completionRate);
            progress.setTotalStudyTime(progress.getTotalStudyTime() + studyTime);
            progress.setLastStudyTime(LocalDateTime.now());
            if (completionRate >= 100) {
                progress.setStatus("completed");
            }
            mapper.update(progress);
        }
        
        // 更新学习计划进度
        updateStudyPlanProgress(userId, courseId);
    }
    
    @Override
    @Transactional
    public void updateStudyPlanProgress(Long userId, Long courseId) {
        // 计算课程完成率
        Double completionRate = calculateCourseCompletionRate(userId, courseId);
        
        // 更新相关学习计划
        try {
            studyPlanService.updatePlanProgressByCourse(userId, courseId, completionRate.intValue());
        } catch (Exception e) {
            // 记录异常但不影响主流程
            System.err.println("更新学习计划进度失败: " + e.getMessage());
        }
    }
    
    @Override
    public Double calculateCourseCompletionRate(Long userId, Long courseId) {
        // 获取用户在该课程下的练习和考试情况
        int practiceCount = mapper.countPracticesByUserAndCourse(userId, courseId);
        int examCount = mapper.countExamsByUserAndCourse(userId, courseId);
        Double averageScore = mapper.getAverageScoreByUserAndCourse(userId, courseId);
        
        // 计算完成率的逻辑，可以根据实际需求调整
        // 这里使用一个简单的算法：如果有考试成绩，以平均分作为完成率；否则根据练习次数计算
        if (averageScore != null) {
            return averageScore;
        } else if (practiceCount > 0) {
            // 假设每个课程预期练习10次为满分
            return Math.min(practiceCount * 10.0, 100.0);
        } else {
            return 0.0;
        }
    }

    private LearningProgressDTO convertToDTO(UserLearningProgress progress) {
        if (progress == null) {
            return new LearningProgressDTO();
        }

        LearningProgressDTO dto = new LearningProgressDTO();
        dto.setProgressId(progress.getProgressId());
        dto.setUserId(progress.getUserId());
        dto.setCourseId(progress.getCourseId());
        dto.setCompletionRate(progress.getCompletionRate());
        dto.setTotalStudyTime(progress.getTotalStudyTime());
        dto.setStatus(progress.getStatus());
        dto.setLastStudyTime(progress.getLastStudyTime());
        return dto;
    }
} 